<?php
/**
 * xml2array() - converte xml in array
 * sXml = stringa xml
 * $aOpt = opzioni [nameSpace] = true : mantiene namespace dei tag; false : li toglie (default)
 */
function xml2array($sXml,$aOpt=array()) {
	$nameSpace = (isset($aOpt['nameSpace']))?$aOpt['nameSpace']:false;
	$withAttr = (isset($aOpt['withAttr']))?$aOpt['withAttr']:false;
	$aRisp = array();
	$aRisp['esito']['cod'] = "999";
	$aRisp['esito']['descr'] = "** errore non definito **";
	$aRisp['aXml'] = array();
	$sXml = trim($sXml);
	if (strlen($sXml)=="" or $sXml[0] != "<") {
		$aRisp['esito']['descr'] = "Errore generico XML risposta";
		$aRisp['esito']['cod'] = '801';
		return $aRisp;
	}
	$oDom = new DOMDocument();
	if (substr($sXml,0,6) != '<?xml ') {
		$sXml = '<?xml version="1.0" encoding="iso-8859-1"?>'.$sXml;
	}
	if(!$oDom->loadXML($sXml) ) {
		$aRisp['esito']['descr'] = "Errore formato XML risposta";
		$aRisp['esito']['cod'] = '802';
		return $aRisp;
	}
	//dbg_("encoding: ".$oDom->encoding." - ".htmlentities(substr($sXml,0,50)));
	$oDomXp = new DOMXPath($oDom);
	$sQuery ="/";
	$nodeList = $oDomXp->query($sQuery);
	$oNode = $nodeList->item(0);
	$aRisp['aXml'] = xml2arrayScan($oNode,$nameSpace,$withAttr);
	$aRisp['esito']['cod'] = "200";
	$aRisp['esito']['descr'] = "OK";
   return $aRisp;
}

function xml2arrayScan($oNode,$nameSpace=false,$withAttr=false) {
	$aChild = array();
	$sText = "";
	//echo "node: ".$oNode->nodeName." ".(($oNode->hasChildNodes())?"ha figli":"non ha figli")." ".$oNode->nodeValue."<BR>";
	if ($oNode->hasChildNodes()) foreach($oNode->childNodes as $oChild) {
		//echo "child: ".$oChild->nodeName."=".$oChild->nodeValue."<br>";
		if ($oChild->nodeName == "#text" or $oChild->nodeName == "#cdata-section") {
			$sText .= $oChild->nodeValue;
			continue;
		}
		if ($nameSpace) {
			$childNodeName = $oChild->nodeName;
		} else {
			$aX = explode(":",$oChild->nodeName);
			$childNodeName = (isset($aX[1]))?$aX[1]:$aX[0];
		}
		$k = 0;
		if (isset($aChild[$childNodeName])) {
			foreach($aChild[$childNodeName] as $kX => $aX) {
				if (is_numeric($kX) and $kX > $k) $k = $kX;
			}
			$k++;
		}
		if ($withAttr) {					
			if ($oChild->hasAttributes()) foreach($oChild->attributes as $oAttr) {
				$aChild[$childNodeName][$k.'A'][$oAttr->name] = $oAttr->value;
			}
		}
		$aChild[$childNodeName][$k] =  xml2arrayScan($oChild,$nameSpace,$withAttr);
	}
	if (count($aChild)>0) return $aChild;
	return $sText;
}  

function x2aPrint($aX, $max=20, $prec="") {
	if (!is_array($aX)) {
		$sX = (strlen($aX) > ($max+10))? substr($aX,0,$max)."... (".strlen($aX).")" : $aX;
		return $prec."   ".$sX."\n";
	}
	$sRet = "";
	foreach($aX as $kX => $bX) {
		$zX = (is_numeric($kX))? $kX:"'$kX'";
		$sRet .= x2aPrint($bX,$max,$prec."[$zX]");
	}
	return $sRet;
}

function x2vPrint($aX, $max=20, $prec="") {
	if (!is_array($aX)) {
		$sX = (strlen($aX) > ($max+10))? substr($aX,0,$max)."... (".strlen($aX).")" : $aX;
		return substr($prec,0,-1)."   ".$sX."\n";
	}
	$sRet = "";
	foreach($aX as $kX => $bX) {
		$zX = (is_numeric($kX))? $kX:"'$kX'";
		$sRet .= x2vPrint($bX,$max,$prec."$zX,");
	}
	return $sRet;
}

function array2xml($aXml) {
	$sXml = '';
	foreach($aXml as $kX => $vX) {
		if (!is_array($vX)) {
			return "<$kX>non conforme - atteso array non stringa</$kX>\n";
		} 
		foreach($vX as $kY => $vY) {
			if (preg_match("/[^0-9]/",$kY)) {
				return "<$kX>non conforme - atteso array semplice</$kX>\n";
			}
			$sXml .= "<$kX>";
			if (is_array($vY)) {
				$sXml .= array2xml($vY);
			} else {
				$sXml .= utf8_encode(htmlspecialchars($vY));
			}
			$sXml .= "</$kX>\n";
		}	
	}	
	return $sXml;
}

function array2xmlView($aXml,$maxLen=50,$nIndent=0) {
	$sXml = '';
	$sInd = "&nbsp;&nbsp;&nbsp;";
	foreach($aXml as $kX => $vX) {
		if (!is_array($vX)) {
			return "tag '$kX' non conforme - atteso array non stringa<pre>".print_r($aXml,1)."</pre>";
		} 
		foreach($vX as $kY => $vY) {
			if (preg_match("/[^0-9]/",$kY)) {
				return "tag '$kX' non conforme - atteso array semplice<pre>".print_r($aXml,1)."</pre>";
			}
			$sXml .= "<br/>".str_repeat($sInd,$nIndent)."&lt;$kX&gt;";
			if (is_array($vY)) {
				$nIndent++;
				$sXml .= array2xmlView($vY, $maxLen, $nIndent);
				$nIndent--;
				$sXml .= "<br/>".str_repeat($sInd,$nIndent)."&lt;/$kX&gt;";
			} else {
				$sXml .= htmlentities(substr($vY,0,$maxLen));
				$sXml .= ((strlen($vY)>$maxLen)?'...('.strlen($vY).')':'');
				$sXml .= "&lt;/$kX&gt;";
			}
		}	
	}	
	return $sXml;
}
